import { Component, OnInit, Output, Input, EventEmitter, Renderer2, OnDestroy } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';


export class Props {
  expandTrigger: string = '';
  multiple: boolean = false;
  checkStrictly: boolean = false;
  emitPath: boolean = true;
  lazy: boolean = false;
  lazyLoad: any = function (node: any, resolve: any) { };
  value: string = 'value';
  label: string = 'label';
  children: string = 'children';
  disabled: string = 'disabled';
  //指定选项的叶子节点的标志位为选项对象的某个属性值
  leaf: string = 'leaf';
}
@Component({
  selector: 'el-cascader',
  templateUrl: './cascader.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: CascaderComponent,
    multi: true
  }],
})
export class CascaderComponent implements OnInit {
  //选中项绑定值
  @Input() model: any = [];
  //选中项绑定值
  @Input() value: any = [];
  //可选项数据源，键名可通过 Props 属性配置
  @Input() options: any = [];
  //配置选项，具体见下表
  @Input() props: Props = new Props();
  //尺寸
  @Input() size: string = '';
  //输入框占位文本
  @Input() placeholder: string = '请选择';
  //是否禁用
  @Input() disabled: boolean = false;
  //是否支持清空选项
  @Input() clearable: boolean = false;
  //输入框中是否显示选中值的完整路径
  @Input('show-all-levels') allLevels: boolean = true;
  //多选模式下是否折叠Tag
  @Input('collapse-tags') collapseTags: boolean = false;
  //选项分隔符
  @Input('separator') separator: string = '/';
  //是否可搜索选项
  @Input('filterable') filterable: boolean = false;
  //搜索关键词输入的去抖延迟，毫秒
  @Input('debounce') debounce: number = 300;
  //自定义浮层类名
  @Input('popper-class') popperClass: string = ' ';
  //自定义搜索逻辑，第一个参数是节点node，第二个参数是搜索关键词keyword，通过返回布尔值表示是否命中
  @Input('ilter-method') ilterMethod: any = function (node: any, keyword: any) { };
  //筛选之前的钩子，参数为输入的值，若返回 false 或者返回 Promise 且被 reject，则停止筛选
  @Input('before-filter') beforeFilter: any = function (value: any) { };

  //当选中节点变化时触发
  @Output('change') modelChange: EventEmitter<any> = new EventEmitter();
  //当展开节点发生变化时触发
  @Output('expand-change') expandChange: EventEmitter<any> = new EventEmitter();
  //下拉框出现/隐藏时触发
  @Output('visible-change') visibleChange: EventEmitter<any> = new EventEmitter();
  //在多选模式下，移除Tag时触发
  @Output('remove-tag') removeTag: EventEmitter<any> = new EventEmitter();

  @Input('empty-text') emptyText: string = '没有数据';


  constructor() {

  }

  ngOnInit(): void {
    console.log(this.props);
  }



  inputHover: boolean = false;
  checkedValue: any = [];
  //显示与隐藏
  menuVisible: boolean = false;

  presentTags: any = [];
  //单选值
  inputValue:string='';
  // private renderer: any;
  // @Input() steps: Array<any> = [];
  // @Input() menuVisible: boolean = false;

  @Input() currentLabels: Array<any> = [];
  // @Input() globalListenFunc: any;
  // @Input('change-on-select') changeOnSelect: boolean = false;
  // @Input() checkStrictly: boolean = false;
  // private controlChange: any = function () { };
  // private controlTouch: any = function () { };


  /**
   * 是否只读
   */
  readonly(): boolean {
    return this.filterable && this.props && this.props.multiple;
  }

  /**
   * 是否多选
   */
  multiple(): boolean {
    return this.props.multiple ? true : false;
  }

  /**
   * 是否可以清除
   */
  showClearIcon(): boolean {
    return !!(this.clearable && this.inputHover && this.inputValue.length);
  }

  //多选删除
  deleteTag(index: number) {
    console.log(index)
  }

  //当展开节点发生变化时触发
  handleExpandChange() {

  }



  /**
   * 选择值改变事件返回
   * @param event 
   */
  toggleDropDownVisible(event:Event) {
    this.menuVisible = false;
    this.model = event;
    if(Array.isArray(event)) {
      var arr:Array<string> = event;
      this.inputValue = this.getTreeTag(arr,this.options,0,[]).join(this.separator);//(event as any).join(this.separator);
    }
    
    this.modelChange.emit(this.model);
  }


  /**
   * 递归
   * @param arr 
   * @param options 
   * @param key 
   * @param tmpArr 
   */
  getTreeTag(arr:Array<string>,options:any[],key:number,tmpArr:Array<string>) : Array<string> {
    options.forEach((item:any)=>{
      if(item[this.props.value] === arr[key]) {
        tmpArr.push(item[this.props.label]);
        if(item[this.props.children] && item[this.props.children].length) {
          tmpArr = this.getTreeTag(arr,item[this.props.children],(key+1),tmpArr);
        }
      }
    });
    return tmpArr;
  }

  clearValue(event: Event): void {
    event.stopPropagation()
    if (this.disabled) return
    this.menuVisible = false;
    this.model = [];
    this.inputValue = '';
  }

  /**
   * 显示与隐藏 下拉框
   * @param event 
   */
  clickHandle(event: MouseEvent): void {
    event.stopPropagation()
    if (this.disabled) return

    const element: HTMLElement = event.target as HTMLElement
    const isSelfTrigger = ['SPAN', 'I', 'INPUT'].find(v => v === element.tagName)

    if (!isSelfTrigger) return
    this.menuVisible = !this.menuVisible;
    this.visibleChange.emit(this.menuVisible);
  }



  //   handleSuggestionClick(index: number) {
  //     console.log(index)
  //   }



  //   toggleDropDownVisible(isEven: boolean) {

  //   }

  //   close(): void {
  //     this.menuVisible = false;
  //     this.globalListenFunc && this.globalListenFunc();
  //   };
  //   clickHandle(event: MouseEvent): void {
  //     event.stopPropagation()
  //     if (this.disabled) return

  //     const element: HTMLElement = event.target as HTMLElement
  //     const isSelfTrigger = ['SPAN', 'I', 'INPUT'].find(v => v === element.tagName)

  //     if (!isSelfTrigger) return
  //     this.menuVisible = !this.menuVisible

  //     if (this.menuVisible) {
  //       this.globalListenFunc = this.renderer.listen(
  //         'document', 'click', () => {
  //           this.menuVisible = false
  //         }
  //       )
  //     } else {
  //       this.globalListenFunc && this.globalListenFunc()
  //     }
  //   }

  //   changeLabels(): void {
  //     const nextValue: Option[] = []
  //     this.steps.forEach((items: Option[]) => {
  //       const steps: Option[] = items.filter((item: Option) => item.active)
  //       nextValue.push(steps[0])
  //     })
  //     this.currentLabels = nextValue
  //     const next = nextValue.map((item: Option) => item.value)
  //     this.model = next
  //     this.modelChange.emit(next)
  //     this.controlChange(next)
  //   }

  //   clearValue(event?: Event): void {
  //     event && event.stopPropagation()
  //     this.currentLabels = []
  //     const step1 = this.options.map((option: Option) =>
  //       Object.assign(option, {
  //         active: false,
  //       }))
  //     this.steps = [step1]
  //     this.menuVisible = false
  //   }

  //   selectHandle(event: Event, step: number, index: number): any {
  //     event.stopPropagation()
  // console.log(event, step, index,this.steps);
  //     if (this.steps[step][index].elDisabled) return
  //     this.steps[step] = this.steps[step].map((item: Option, i: number) =>
  //       Object.assign(item, { active: i === index }))
  //     // reset steps
  //     this.steps.length = step + 1
  //     const next = this.steps[step][index].children

  //     // go next
  //     if (next && Array.isArray(next)) {
  //       // change on select (props)
  //       this.changeOnSelect && this.changeLabels()
  //       const nativeNext = next.map((item: Option) => Object.assign(item, { active: false }))
  //       return this.steps.push(nativeNext)
  //     }
  //     // last step
  //     this.changeLabels()
  //     this.menuVisible = false
  //   }



  //   ngOnInit(): void {
  //     this.clearValue()
  //     if (this.model && this.model.length) {
  //       const getLabel = (options: Option[], val: string) => {
  //         const item: Option = options.filter((item: Option) => item.value === val)[0]
  //         return { children: item.children, val: item }
  //       }

  //       let options: any = this.options
  //       const val: Option[] = this.model.map((v: string) => {
  //         const { children, val } = getLabel(options, v)
  //         options = children
  //         return val
  //       })
  //       this.currentLabels = val.filter(v => !!v)

  //     }
  //   }

  //   ngOnDestroy(): void {
  //     this.globalListenFunc && this.globalListenFunc()
  //   }

  //   writeValue(value: any): void {
  //     this.model = value
  //   }

  //   registerOnChange(fn: Function): void {
  //     this.controlChange = fn
  //   }

  //   registerOnTouched(fn: Function): void {
  //     this.controlTouch = fn
  //   }
}
